package com.korion.channel

import android.util.Log
import java.lang.Exception
import java.net.InetAddress
import java.net.InetSocketAddress
import java.net.ServerSocket
import java.net.SocketAddress
import kotlin.concurrent.thread


interface IServerListener{
    fun onServerStart(localAddress: String?)
    fun onNewConnection(channel: IChannel, remoteAddress: String, port: Int)
    fun onServerClose()
}

class Server private constructor(host: String, port: Int, listener: IServerListener){

    private var daemon: Thread? = null
    private val mHost = host
    private val mListenPort = port
    private val mListener: IServerListener = listener
    @Volatile
    private var mStopServer = false
    private var mAddress: SocketAddress? = null

    companion object{
        private const val TAG = "Channel Server"
        private const val DAEMON_NAME = "Connection-daemon"
        fun listen(host: String, port: Int, listener: IServerListener): Server {
            val server = Server(host, port, listener)
            server.init()
            return server
        }
    }

    fun init(){
        if (daemon != null && daemon!!.isAlive){
            return
        }
        daemon = thread(name = DAEMON_NAME, isDaemon = true) {
            val serverSocket = ServerSocket()
            serverSocket.bind(InetSocketAddress(mHost, mListenPort))
            mAddress = serverSocket.localSocketAddress
            mListener.onServerStart(mAddress.toString())
            while (!mStopServer){
                try {
                    val socket = serverSocket.accept()
                    Log.d(TAG, "${socket.remoteSocketAddress}:${socket.port}已连接...")
                    val channel = Channel(socket)
                    if (!mStopServer){
                        mListener.onNewConnection(channel, socket.remoteSocketAddress.toString(), socket.port)
                    }
                } catch (e: Exception){
                    Log.d(TAG, e.message)
                    break
                }
            }
            mListener.onServerClose()
            serverSocket.closeSafely()

        }
    }

    fun stop(){
        mStopServer = true
    }

    fun getLocalAddress(): String?{
        return mAddress?.toString()
    }

}
